﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace Pyramid_Game
{
    /// <summary>
    /// [미니게임] 왕의 방문 찾기
    /// </summary>
    public class FindOfRoom : GameScreen
    {
        #region Declarations
        //배경 이미지
        Texture2D findOfRoomTexture;

        //다음 페이지로 넘길지
        bool nextPage = false;
        //이전 페이지로 넘길지
        bool previousPage = false;
        //문의 관한 정보가 담긴 Door 클래스의 List 
        List<Door> doors = new List<Door>();

        bool start = false;
        bool clear = false;
        /// <summary>
        /// 클리어타임 계산을 위한 변수들
        /// </summary>
        double clearTime;
        double startTime;

        //힌트창 표현을 위한 클래스
        Hint hint;
        int hintSize = 80;
        int answer=0;
        float velocity = 1000;

        List<int> doorHeight = new List<int>();
        List<int> doorWidth = new List<int>();

        float distance = 0;
        float delta = 0;
        #endregion

        #region Constructor

        public FindOfRoom()
        {
            //줄에 따른 문의 높이 값
            doorHeight.Add(50);
            doorHeight.Add(450);
            doorHeight.Add(850);
            doorHeight.Add(1250);
            doorHeight.Add(1650);
            doorHeight.Add(2050);
            //X 값
            doorWidth.Add(60);
            doorWidth.Add(245);
            doorWidth.Add(430);
            doorWidth.Add(615);

            AddDoors();

            hint = new Hint(answer);
        }

        #endregion

        #region LoadContent

        public override void LoadContent(ContentManager content)
        {
            findOfRoomTexture = content.Load<Texture2D>("Texture/door/findroom");

            foreach (Door d in doors)
            {
                d.LoadContent(content);
            }
            screenManager.AddScreen(hint);
        }

        #endregion

        #region Update

        public override void Update(Touch touch, GameTime gameTime)
        {
            //시작 시간을 저장, 클리어타임 계산을 위해
            if (!start)
            {
                startTime = gameTime.TotalGameTime.TotalSeconds;
                start = true;
            }
            if (clear)
            {
                End(touch, gameTime);
                return;
            }

            if(!nextPage && !previousPage)
                HandleInput(touch, gameTime);

            if (nextPage)
            {
                float movement = velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

                foreach (Door d in doors)
                {
                    d.PositionY -= movement;
                }
                distance -= movement;

                if (distance <= 0)
                {
                    foreach (Door d in doors)
                    {
                        d.PositionY += Math.Abs(distance);
                    }

                    distance = 0;
                    delta = 0;
                    nextPage = false;
                }
            }
            else if (previousPage)
            {
                float movement = velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

                foreach (Door d in doors)
                {
                    d.PositionY += movement;
                }
                distance -= movement;

                if (distance <= 0)
                {
                    foreach (Door d in doors)
                    {
                        d.PositionY -= Math.Abs(distance);
                    }

                    distance = 0;
                    delta = 0;
                    previousPage = false;
                }
            }
        }
        public void HandleInput(Touch touch, GameTime gameTime)
        {
            foreach (GestureSample gesture in touch.Gestures)
            {
                Point tapLocation = new Point((int)gesture.Position.X, (int)gesture.Position.Y);
                
                if (gesture.GestureType == GestureType.FreeDrag)
                {
                    if (doors[0].PositionY + gesture.Delta.Y > doorHeight[0])
                        break;
                    if (Boundary(gesture.Delta.Y))
                        break;

                    delta += gesture.Delta.Y;
                    foreach (Door d in doors)
                    {
                        d.PositionY += gesture.Delta.Y;
                    }
                }
                else if (gesture.GestureType == GestureType.DragComplete)
                {
                    if (delta < 0)
                    {
                        distance = 400 - Math.Abs(delta);
                        nextPage = true;
                    }
                    else if (delta > 0)
                    {
                        distance = 400 - Math.Abs(delta);
                        previousPage = true;
                    }
                }
                else if (gesture.GestureType == GestureType.Tap)
                {
                    //문을 선택했을 때 처리하는 부분
                    foreach (Door d in doors)
                    {
                        if (tapLocation.X > d.Position.X &&
                        tapLocation.X < d.Position.X + d.DoorTexture.Width &&
                        tapLocation.Y > d.Position.Y &&
                        tapLocation.Y < d.Position.Y + d.DoorTexture.Height)
                        {
                            //정답인 문을 선택했을 때 
                            if (d.Answer)
                            {
                                clearTime = gameTime.TotalGameTime.TotalSeconds;
                                screenManager.AddScreen(new Correct());
                                clear = true;
                                return;
                            }
                            else if (!d.Answer)
                            {
                                screenManager.AddScreen(new Incorrect());
                            }
                        }
                    }
                }
            }
        }
        public bool Boundary(float valueY)
        {
            if (GameConstants.stage == 1)
            {
                if (doors[12].PositionY + valueY < doorHeight[0])
                    return true;
            }
            else if (GameConstants.stage == 2)
            {
                if (doors[16].PositionY + valueY < doorHeight[0])
                    return true;
            }
            else if (GameConstants.stage == 3)
            {
                if (doors[20].PositionY + valueY < doorHeight[0])
                    return true;
            }
            return false;
        }

        #endregion

        #region Draw

        public override void Draw(SpriteBatch spriteBatch, GameTime gameTime)
        {
            spriteBatch.Draw(findOfRoomTexture, new Rectangle(0, 0, Game1.viewport.Width, 400), Color.White);

            foreach (Door d in doors)
            {
                d.Draw(spriteBatch, gameTime);
            }
        }

        #endregion

        #region HelperMethods

        public void AddDoors()
        {
            int size=24;
            int minus = 0;

            doors.Clear();

            Random rand = new Random(Int32.Parse(DateTime.Now.ToString("HHmmss")));

            if (GameConstants.stage == 1)
            {
                size = 16;
                minus = 2;
            }
            else if(GameConstants.stage == 2)
            {
                size = 20;
                minus = 1;
            }
            else if (GameConstants.stage == 3)
            {
                size = 24;
                minus = 0;
            }

            answer = rand.Next(0, size);

            for (int i = 0; i < doorHeight.Count() - minus; i++)
            {
                for (int j = 0; j < doorWidth.Count(); j++)
                {
                    int type = rand.Next(0, size);
                    int save = j;

                    foreach (Door d in doors)
                    {
                        if (d.Type == type)
                        {
                            j--;
                            break;
                        }
                    }
                    if (save == j)
                    {
                        //%4 삭제
                        if (type == answer)
                            doors.Add(new Door(true, type % 4, new Vector2(doorWidth[j], doorHeight[i])));
                        else
                            doors.Add(new Door(false, type % 4, new Vector2(doorWidth[j], doorHeight[i])));
                    }
                }
            }
        }

        public void End(Touch touch, GameTime gameTime)
        {
            foreach (GestureSample gesture in touch.Gestures)
            {
                if (gesture.GestureType == GestureType.Tap)
                {
                    hint.RemoveThis();
                    screenManager.RemoveScreen(this);
                    screenManager.AddScreen(new resultScreen(clearTime - startTime, "FindOfRoom"));
                }
            }

            if (clearTime + 1 < gameTime.TotalGameTime.TotalSeconds)
            {
                hint.RemoveThis();
                screenManager.RemoveScreen(this);
                screenManager.AddScreen(new resultScreen(clearTime - startTime, "FindOfRoom"));
            }
        }

        #endregion
    }
}
